Imports System
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters

Namespace Modules
    ''' <summary>
    ''' Class used for object persistance
    ''' </summary>
    ''' <remarks></remarks>
    <ObfuscationAttribute(Exclude:=True, ApplyToMembers:=True)> _
    Public Class ObjectPersistance(Of vType)
        Public Enum SaveState As Byte
            XML
            Binary
        End Enum

        Private mSaveState As SaveState = ObjectPersistance(Of vType).SaveState.Binary

        Sub New(Optional ByVal Type As SaveState = ObjectPersistance(Of vType).SaveState.Binary)
            mSaveState = Type
        End Sub

        Public Function LoadFromFile(ByVal filename As String) As vType
            Dim obj As vType = Nothing
            Dim openStream As FileStream = Nothing

            Try
                openStream = New FileStream(filename, FileMode.Open)
                Dim formatter As IFormatter = Nothing

                ' Generate the correct formatter!
                Select Case mSaveState
                    Case ObjectPersistance(Of vType).SaveState.Binary
                        formatter = New Binary.BinaryFormatter
                    Case ObjectPersistance(Of vType).SaveState.XML
                        formatter = New Soap.SoapFormatter
                    Case Else
                        Return Nothing
                End Select

                obj = CType(formatter.Deserialize(openStream), vType)

            Catch ex As Exception
            Finally
                If Not IsNothing(openStream) Then openStream.Close()
            End Try

            Return obj

        End Function

        Public Function LoadFromStream(ByVal stream As IO.Stream, ByRef [Object] As vType) As Boolean
            Dim obj As vType = Nothing

            Try
                Dim formatter As IFormatter = Nothing

                ' Generate the correct formatter!
                Select Case mSaveState
                    Case ObjectPersistance(Of vType).SaveState.Binary
                        formatter = New Binary.BinaryFormatter
                    Case ObjectPersistance(Of vType).SaveState.XML
                        formatter = New Soap.SoapFormatter
                    Case Else
                        Return Nothing
                End Select

                obj = CType(formatter.Deserialize(stream), vType)

                [Object] = obj
                Return True
            Catch ex As Exception

            End Try

            Return False
        End Function

        Public Function LoadFromStreamAndUnCompress(ByVal stream As IO.Stream, ByRef [Object] As vType) As Boolean
            Dim uncompressed As New MemoryStream
            Dim zipStream As New IO.Compression.GZipStream(stream, Compression.CompressionMode.Decompress, True)

            ' Uncompress the stream into a new memory stream
            Dim bytes(100000 - 1) As Byte
            Dim length As Integer = zipStream.Read(bytes, 0, 100000)
            While length > 0
                uncompressed.Write(bytes, 0, length)
                length = zipStream.Read(bytes, 0, 100000)
            End While
            uncompressed.Flush()
            zipStream.Flush()
            zipStream.Close()

            ' Set to the begining of the stream
            uncompressed.Seek(0, SeekOrigin.Begin)

            ' Load the object and return appropriate value also clear out the buffers
            If LoadFromStream(uncompressed, [Object]) Then
                uncompressed.Close()
                GC.Collect()
                Return True
            Else
                uncompressed.Close()
                GC.Collect()
                Return False
            End If
        End Function

        Public Function SaveToFile(ByVal filename As String, ByVal [Object] As vType) As Boolean
            Dim saveStream As FileStream = Nothing
            Dim returnvalue As Boolean = False
            Try
                ' Open the file stream
                saveStream = New FileStream(filename, FileMode.OpenOrCreate)
                Dim formatter As IFormatter = Nothing

                ' Generate the correct formatter!
                Select Case mSaveState
                    Case ObjectPersistance(Of vType).SaveState.Binary
                        formatter = New Binary.BinaryFormatter
                    Case ObjectPersistance(Of vType).SaveState.XML
                        formatter = New Soap.SoapFormatter
                    Case Else
                        Return False
                End Select

                ' Serialise the object
                formatter.Serialize(saveStream, [Object])
                returnvalue = True

            Catch ex As Exception

            Finally
                If Not IsNothing(saveStream) Then saveStream.Close()
            End Try

            Return False
        End Function

        Public Function SaveToStream(ByVal Stream As IO.Stream, ByVal [Object] As vType) As Boolean
            Dim returnValue As Boolean = False
            Try
                Dim formatter As IFormatter = Nothing

                ' Generate the correct formatter!
                Select Case mSaveState
                    Case ObjectPersistance(Of vType).SaveState.Binary
                        formatter = New Binary.BinaryFormatter
                    Case ObjectPersistance(Of vType).SaveState.XML
                        formatter = New Soap.SoapFormatter
                    Case Else
                        Return Nothing
                End Select

                formatter.Serialize(Stream, [Object])

                returnValue = True
            Catch ex As Exception
                returnValue = False
            End Try

            Return returnValue
        End Function

        Public Function SaveToStreamAndCompress(ByRef stream As IO.Stream, ByVal [Object] As vType) As Boolean
            Dim serialStream As New MemoryStream
            If SaveToStream(serialStream, [Object]) Then
                ' Ensure the serial stream is at the begining
                serialStream.Seek(0, SeekOrigin.Begin)

                Dim compressed As New MemoryStream
                Dim zipStream As New IO.Compression.GZipStream(compressed, Compression.CompressionMode.Compress, True)
                Dim bytes(100000 - 1) As Byte
                Dim length As Integer = serialStream.Read(bytes, 0, 100000)
                While length > 0
                    zipStream.Write(bytes, 0, length)
                    length = serialStream.Read(bytes, 0, 100000)
                End While
                zipStream.Flush()
                zipStream.Close()

                compressed.Seek(0, SeekOrigin.Begin)

                stream = compressed

                GC.Collect()

                Return True
            Else
                stream = Nothing
                Return False
            End If

        End Function

    End Class
End Namespace